home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n03 / dflt10.exe / DIALBOX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-21  |  20.3 KB  |  882 lines

  1. /* ----------------- dialbox.c -------------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static char path[MAXPATH];
  6. static char drive[MAXDRIVE] = " :";
  7. static char dir[MAXDIR];
  8. static char name[MAXFILE];
  9. static char ext[MAXEXT];
  10.  
  11. static int inFocusCommand(DBOX *);
  12. static void dbShortcutKeys(DBOX *, int);
  13. static int ControlProc(WINDOW, MESSAGE, PARAM, PARAM);
  14. static void ChangeFocus(WINDOW, int);
  15. static CTLWINDOW *AssociatedControl(DBOX *, enum commands);
  16. static void SetRadioButton(DBOX *, CTLWINDOW *);
  17.  
  18. static int SysMenuOpen;
  19.  
  20. int DialogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  21. {
  22.     DBOX *db = wnd->extension;
  23.     CTLWINDOW *ct;
  24.     WINDOW cwnd;
  25.     int rtn;
  26.  
  27.     switch (msg)    {
  28.         case CREATE_WINDOW:
  29.             rtn = BaseWndProc(DIALOG, wnd, msg, p1, p2);
  30.             ct = db->ctl;
  31.             while (ct->class)    {
  32.                 int attrib = VISIBLE;
  33.                 if (TestAttribute(wnd, NOCLIP))
  34.                     attrib |= NOCLIP;
  35.                 if (wnd->Modal)
  36.                     attrib |= SAVESELF;
  37.                 ct->setting = ct->isetting;
  38.                 if (ct->class == EDITBOX && ct->dwnd.h > 1)
  39.                     attrib |= (MULTILINE | HASBORDER);
  40.                 else if (ct->class == LISTBOX || ct->class == TEXTBOX)
  41.                     attrib |= HASBORDER;
  42.                 cwnd = CreateWindow(ct->class,
  43.                              ct->dwnd.title,
  44.                              ct->dwnd.x+GetClientLeft(wnd),
  45.                              ct->dwnd.y+GetClientTop(wnd),
  46.                              ct->dwnd.h,
  47.                              ct->dwnd.w,
  48.                              ct,
  49.                              wnd,
  50.                              ControlProc,
  51.                              attrib);
  52.                 if ((ct->class == EDITBOX ||
  53.                         ct->class == COMBOBOX) &&
  54.                             ct->itext != NULL)
  55.                     SendMessage(cwnd, SETTEXT, (PARAM) ct->itext, 0);
  56.                 if (ct->class != BOX &&
  57.                     ct->class != TEXT &&
  58.                         wnd->dFocus == NULL)
  59.                     wnd->dFocus = ct;
  60.                 ct++;
  61.             }
  62.             return rtn;
  63.         case SETFOCUS:
  64.             if (wnd->Modal)    {
  65.                 if (p1)
  66.                     SendMessage(inFocus, SETFOCUS, FALSE, 0);
  67.                 inFocus = p1 ? wnd : NULL;
  68.                 return TRUE;
  69.             }
  70.             break;
  71.         case SHIFT_CHANGED:
  72.             if (wnd->Modal)
  73.                 return TRUE;
  74.             break;
  75.         case LEFT_BUTTON:
  76.             if (WindowSizing || WindowMoving)
  77.                 return FALSE;
  78.             if (HitControlBox(wnd, p1-GetLeft(wnd), p2-GetTop(wnd)))    {
  79.                 PostMessage(wnd, KEYBOARD, ' ', ALTKEY);
  80.                 return TRUE;
  81.             }
  82.             ct = db->ctl;
  83.             while (ct->class)    {
  84.                 WINDOW cwnd = ct->wnd;
  85.                 if (ct->class == COMBOBOX)    {
  86.                     if (p2 == GetTop(cwnd))    {
  87.                         if (p1 == GetRight(cwnd)+1)    {
  88.                             SendMessage(cwnd, msg, p1, p2);
  89.                             return TRUE;
  90.                         }
  91.                     }
  92.                     if (GetClass(inFocus) == LISTBOX)
  93.                         SendMessage(wnd, SETFOCUS, TRUE, 0);
  94.                 }
  95.                 else if (ct->class == SPINBUTTON)    {
  96.                     if (p2 == GetTop(cwnd))    {
  97.                         if (p1 == GetRight(cwnd)+1 ||
  98.                                 p1 == GetRight(cwnd)+2)    {
  99.                             SendMessage(cwnd, msg, p1, p2);
  100.                             return TRUE;
  101.                         }
  102.                     }
  103.                 }
  104.                 ct++;
  105.             }
  106.             break;
  107.         case KEYBOARD:
  108.             if (WindowMoving || WindowSizing)
  109.                 break;
  110.             switch ((int)p1)    {
  111.                 case F1:
  112.                     ct = wnd->dFocus;
  113.                     if (ct != NULL)
  114.                         if (DisplayHelp(wnd, ct->help))
  115.                             return TRUE;
  116.                     break;
  117.                 case SHIFT_HT:
  118.                 case BS:
  119.                 case UP:
  120.                     ChangeFocus(wnd, FALSE);
  121.                     break;
  122.                 case ALT_F6:
  123.                 case '\t':
  124.                 case FWD:
  125.                 case DN:
  126.                     ChangeFocus(wnd, TRUE);
  127.                     break;
  128.                 case ' ':
  129.                     if (((int)p2 & ALTKEY) && TestAttribute(wnd, CONTROLBOX))    {
  130.                         SysMenuOpen = TRUE;
  131.                         BuildSystemMenu(wnd);
  132.                     }
  133.                     break;
  134.                 case CTRL_F4:
  135.                 case ESC:
  136.                     SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  137.                     break;
  138.                 default:
  139.                     /* ------ search all the shortcut keys ----- */
  140.                     dbShortcutKeys(db, (int) p1);
  141.                     break;
  142.             }
  143.             if (wnd->Modal)
  144.                 return TRUE;
  145.             break;
  146.         case CLOSE_POPDOWN:
  147.             SysMenuOpen = FALSE;
  148.             break;
  149.         case LB_SELECTION:
  150.         case LB_CHOOSE:
  151.             if (SysMenuOpen)
  152.                 return TRUE;
  153.             SendMessage(wnd, COMMAND, inFocusCommand(db), msg);
  154.             break;
  155.         case COMMAND:
  156.             switch ((int) p1)    {
  157.                 case ID_OK:
  158.                 case ID_CANCEL:
  159.                     if ((int)p2 != 0)
  160.                         return TRUE;
  161.                     wnd->ReturnCode = (int) p1;
  162.                     if (wnd->Modal)
  163.                         PostMessage(wnd, ENDDIALOG, 0, 0);
  164.                     else
  165.                         SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
  166.                     return TRUE;
  167.                 case ID_HELP:
  168.                     if ((int)p2 != 0)
  169.                         return TRUE;
  170.                     return DisplayHelp(wnd, db->HelpName);
  171.                 default:
  172.                     break;
  173.             }
  174.             break;
  175.         case PAINT:
  176.             p2 = TRUE;
  177.             break;
  178.         case CLOSE_WINDOW:
  179.             if (!p1)    {
  180.                 SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  181.                 return TRUE;
  182.             }
  183.             break;
  184.         default:
  185.             break;
  186.     }
  187.     return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  188. }
  189.  
  190. int DialogBox(WINDOW wnd, DBOX *db, int Modal,
  191.     int (*wndproc)(struct window *, enum messages, PARAM, PARAM))
  192. {
  193.     int rtn;
  194.     int x = db->dwnd.x, y = db->dwnd.y;
  195.     CTLWINDOW *ct;
  196.     WINDOW oldFocus = inFocus;
  197.     WINDOW DialogWnd;
  198.  
  199.     if (!Modal && wnd != NULL)    {
  200.         x += GetLeft(wnd);
  201.         y += GetTop(wnd);
  202.     }
  203.     DialogWnd = CreateWindow(DIALOG,
  204.                         db->dwnd.title,
  205.                         x, y,
  206.                         db->dwnd.h,
  207.                         db->dwnd.w,
  208.                         db,
  209.                         wnd,
  210.                         wndproc,
  211.                         Modal ? SAVESELF : 0);
  212.     DialogWnd->Modal = Modal;
  213.     SendMessage(((CTLWINDOW *)(DialogWnd->dFocus))->wnd, SETFOCUS, TRUE, 0);
  214.     SendMessage(DialogWnd, SHOW_WINDOW, 0, 0);
  215.     SendMessage(DialogWnd, INITIATE_DIALOG, 0, 0);
  216.     if (Modal)    {
  217.         SendMessage(DialogWnd, CAPTURE_MOUSE, 0, 0);
  218.         SendMessage(DialogWnd, CAPTURE_KEYBOARD, 0, 0);
  219.         while (dispatch_message())
  220.             ;
  221.         rtn = DialogWnd->ReturnCode == ID_OK;
  222.         SendMessage(DialogWnd, RELEASE_MOUSE, 0, 0);
  223.         SendMessage(DialogWnd, RELEASE_KEYBOARD, 0, 0);
  224.         SendMessage(inFocus, SETFOCUS, FALSE, 0);
  225.         SendMessage(DialogWnd, CLOSE_WINDOW, TRUE, 0);
  226.         SendMessage(oldFocus, SETFOCUS, TRUE, 0);
  227.         if (rtn)    {
  228.             ct = db->ctl;
  229.             while (ct->class)    {
  230.                 ct->wnd = NULL;
  231.                 if (ct->class == RADIOBUTTON || ct->class == CHECKBOX)
  232.                     ct->isetting = ct->setting;
  233.                 ct++;
  234.             }
  235.         }
  236.         return rtn;
  237.     }
  238.     return FALSE;
  239. }
  240.  
  241. static int inFocusCommand(DBOX *db)
  242. {
  243.     CTLWINDOW *ct = db->ctl;
  244.     while (ct->class)    {
  245.         if (ct->wnd == inFocus)
  246.             return ct->command;
  247.         ct++;
  248.     }
  249.     return -1;
  250. }
  251.  
  252. CTLWINDOW *FindCommand(DBOX *db, enum commands cmd, int class)
  253. {
  254.     CTLWINDOW *ct = db->ctl;
  255.     while (ct->class)    {
  256.         if (ct->class == class)
  257.             if (cmd == ct->command)
  258.                 return ct;
  259.         ct++;
  260.     }
  261.     return NULL;
  262. }
  263.  
  264. WINDOW ControlWindow(DBOX *db, enum commands cmd)
  265. {
  266.     CTLWINDOW *ct = db->ctl;
  267.     while (ct->class)    {
  268.         if (ct->class != TEXT && cmd == ct->command)
  269.             return ct->wnd;
  270.         ct++;
  271.     }
  272.     return NULL;
  273. }
  274.  
  275. void PushRadioButton(DBOX *db, enum commands cmd)
  276. {
  277.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  278.     if (ct != NULL)    {
  279.         SetRadioButton(db, ct);
  280.         ct->isetting = ON;
  281.     }
  282. }
  283.  
  284. static struct {
  285.     CTLWINDOW *rct;
  286. } rbs[MAXRADIOS];
  287.  
  288. static void SetRadioButton(DBOX *db, CTLWINDOW *ct)
  289. {
  290.     CTLWINDOW *ctt = db->ctl;
  291.     int i;
  292.  
  293.     /* --- clear all the radio buttons
  294.                 in this group on the dialog box --- */
  295.  
  296.     /* -------- build a table of all radio buttons at the
  297.             same x vector ---------- */
  298.     for (i = 0; i < MAXRADIOS; i++)
  299.         rbs[i].rct = NULL;
  300.     while (ctt->class)    {
  301.         if (ctt->class == RADIOBUTTON)
  302.             if (ct->dwnd.x == ctt->dwnd.x)
  303.                 rbs[ctt->dwnd.y].rct = ctt;
  304.         ctt++;
  305.     }
  306.  
  307.     /* ----- find the start of the radiobutton group ---- */
  308.     i = ct->dwnd.y;
  309.     while (i >= 0 && rbs[i].rct != NULL)
  310.         --i;
  311.     /* ---- ignore everthing before the group ------ */
  312.     while (i >= 0)
  313.         rbs[i--].rct = NULL;
  314.  
  315.     /* ----- find the end of the radiobutton group ---- */
  316.     i = ct->dwnd.y;
  317.     while (i < MAXRADIOS && rbs[i].rct != NULL)
  318.         i++;
  319.     /* ---- ignore everthing past the group ------ */
  320.     while (i < MAXRADIOS)
  321.         rbs[i++].rct = NULL;
  322.  
  323.     for (i = 0; i < MAXRADIOS; i++)    {
  324.         if (rbs[i].rct != NULL)    {
  325.             int wason = rbs[i].rct->setting;
  326.             rbs[i].rct->setting = OFF;
  327.             if (wason)
  328.                 SendMessage(rbs[i].rct->wnd, PAINT, 0, 0);
  329.         }
  330.     }
  331.     ct->setting = ON;
  332.     SendMessage(ct->wnd, PAINT, 0, 0);
  333. }
  334.  
  335. int RadioButtonSetting(DBOX *db, enum commands cmd)
  336. {
  337.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  338.     if (ct != NULL)
  339.         return (ct->setting == ON);
  340.     return FALSE;
  341. }
  342.  
  343. static void ControlSetting(DBOX *db, enum commands cmd,
  344.                                     int class, int setting)
  345. {
  346.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  347.     if (ct != NULL)
  348.         ct->isetting = setting;
  349. }
  350.  
  351. void SetCheckBox(DBOX *db, enum commands cmd)
  352. {
  353.     ControlSetting(db, cmd, CHECKBOX, ON);
  354. }
  355.  
  356. void ClearCheckBox(DBOX *db, enum commands cmd)
  357. {
  358.     ControlSetting(db, cmd, CHECKBOX, OFF);
  359. }
  360.  
  361. void EnableButton(DBOX *db, enum commands cmd)
  362. {
  363.     ControlSetting(db, cmd, BUTTON, ON);
  364. }
  365.  
  366. void DisableButton(DBOX *db, enum commands cmd)
  367. {
  368.     ControlSetting(db, cmd, BUTTON, OFF);
  369. }
  370.  
  371. int CheckBoxSetting(DBOX *db, enum commands cmd)
  372. {
  373.     CTLWINDOW *ct = FindCommand(db, cmd, CHECKBOX);
  374.     if (ct != NULL)
  375.         return (ct->isetting == ON);
  376.     return FALSE;
  377. }
  378.  
  379. char *GetDlgTextString(DBOX *db, enum commands cmd, CLASS class)
  380. {
  381.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  382.     if (ct != NULL)
  383.         return ct->itext;
  384.     else
  385.         return NULL;
  386. }
  387.  
  388. void SetDlgTextString(DBOX *db, enum commands cmd, char *text, CLASS class)
  389. {
  390.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  391.     if (ct != NULL)    {
  392.         ct->itext = realloc(ct->itext, strlen(text)+1);
  393.         if (ct->itext != NULL)
  394.             strcpy(ct->itext, text);
  395.     }
  396. }
  397.  
  398. void PutComboListText(WINDOW wnd, enum commands cmd, char *text)
  399. {
  400.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  401.     if (ct != NULL)        {
  402.         WINDOW lwnd = ((WINDOW)(ct->wnd))->extension;
  403.         SendMessage(lwnd, ADDTEXT, (PARAM) text, 0);
  404.     }
  405. }
  406.  
  407. void PutItemText(WINDOW wnd, enum commands cmd, char *text)
  408. {
  409.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  410.  
  411.     if (ct == NULL)
  412.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  413.     if (ct == NULL)
  414.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  415.     if (ct == NULL)
  416.         ct = FindCommand(wnd->extension, cmd, LISTBOX);
  417.     if (ct == NULL)
  418.         ct = FindCommand(wnd->extension, cmd, SPINBUTTON);
  419.     if (ct == NULL)
  420.         ct = FindCommand(wnd->extension, cmd, TEXT);
  421.     if (ct != NULL)        {
  422.         WINDOW cwnd = (WINDOW) (ct->wnd);
  423.         switch (ct->class)    {
  424.             case COMBOBOX:
  425.             case EDITBOX:
  426.                 SendMessage(cwnd, CLEARTEXT, 0, 0);
  427.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  428.                 if (!isMultiLine(cwnd))
  429.                     SendMessage(cwnd, PAINT, 0, 0);
  430.                 break;
  431.             case LISTBOX:
  432.             case TEXTBOX:
  433.             case SPINBUTTON:
  434.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  435.                 break;
  436.             case TEXT:    {
  437.                 SendMessage(cwnd, CLEARTEXT, 0, 0);
  438.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  439.                 SendMessage(cwnd, PAINT, 0, 0);
  440.                 break;
  441.             }
  442.             default:
  443.                 break;
  444.         }
  445.     }
  446. }
  447.  
  448. void GetItemText(WINDOW wnd, enum commands cmd, char *text, int len)
  449. {
  450.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  451.  
  452.     if (ct == NULL)
  453.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  454.     if (ct == NULL)
  455.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  456.     if (ct == NULL)
  457.         ct = FindCommand(wnd->extension, cmd, TEXT);
  458.     if (ct != NULL)    {
  459.         WINDOW cwnd = (WINDOW) (ct->wnd);
  460.         if (cwnd != NULL)    {
  461.             switch (ct->class)    {
  462.                 case TEXT:
  463.                     if (GetText(cwnd) != NULL)    {
  464.                         unsigned char *cp = strchr(GetText(cwnd), '\n');
  465.                         if (cp != NULL)
  466.                             len = (int) (cp - GetText(cwnd));
  467.                         strncpy(text, GetText(cwnd), len);
  468.                         *(text+len) = '\0';
  469.                     }
  470.                     break;
  471.                 case TEXTBOX:
  472.                     if (GetText(cwnd) != NULL)
  473.                         strncpy(text, GetText(cwnd), len);
  474.                     break;
  475.                 case COMBOBOX:
  476.                 case EDITBOX:
  477.                     SendMessage(cwnd, GETTEXT, (PARAM) text, len);
  478.                     break;
  479.                 default:
  480.                     break;
  481.             }
  482.         }
  483.     }
  484. }
  485.  
  486. void GetDlgListText(WINDOW wnd, char *text, enum commands cmd)
  487. {
  488.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, LISTBOX);
  489.     int sel = SendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0);
  490.     SendMessage(ct->wnd, LB_GETTEXT, (PARAM) text, sel);
  491. }
  492.  
  493. static int dircmp(const void *c1, const void *c2)
  494. {
  495.     return stricmp(*(char **)c1, *(char **)c2);
  496. }
  497.  
  498. int DlgDirList(WINDOW wnd, char *fspec,
  499.                 enum commands nameid, enum commands pathid,
  500.                 unsigned attrib)
  501. {
  502.     int ax, i = 0, criterr = 1;
  503.     struct ffblk ff;
  504.     CTLWINDOW *ct = FindCommand(wnd->extension, nameid, LISTBOX);
  505.     WINDOW lwnd;
  506.     char **dirlist = NULL;
  507.  
  508.     CreatePath(path, fspec, TRUE, TRUE);
  509.  
  510.     if (ct != NULL)    {
  511.         lwnd = ct->wnd;
  512.         SendMessage(ct->wnd, CLEARTEXT, 0, 0);
  513.  
  514.         if (attrib & 0x8000)    {
  515.             union REGS regs;
  516.             char drname[15];
  517.             unsigned int cd, dr;
  518.  
  519.             cd = getdisk();
  520.             for (dr = 0; dr < 26; dr++)    {
  521.                 unsigned ndr;
  522.                 setdisk(dr);
  523.                 ndr = getdisk();
  524.                 if (ndr == dr)    {
  525.                     /* ------- test for remapped B drive ------- */
  526.                     if (dr == 1)    {
  527.                         regs.x.ax = 0x440e;        /* IOCTL function 14 */
  528.                         regs.h.bl = dr+1;
  529.                         int86(DOS, ®s, ®s);
  530.                         if (regs.h.al != 0)
  531.                             continue;
  532.                     }
  533.  
  534.                     sprintf(drname, "[%c:]", dr+'A');
  535.  
  536.                     /* ------ test for network or RAM disk ---- */
  537.                     regs.x.ax = 0x4409;        /* IOCTL function 9 */
  538.                     regs.h.bl = dr+1;
  539.                     int86(DOS, ®s, ®s);
  540.                     if (!regs.x.cflag)    {
  541.                         if (regs.x.dx & 0x1000)
  542.                             strcat(drname, " (Network)");
  543.                         else if (regs.x.dx == 0x0800)
  544.                             strcat(drname, " (RAMdisk)");
  545.                     }
  546.                     SendMessage(lwnd, ADDTEXT, (PARAM) drname, 0);
  547.                 }
  548.             }
  549.             setdisk(cd);
  550.         }
  551.  
  552.         while (criterr == 1)    {
  553.             ax = findfirst(path, &ff, attrib & 0x3f);
  554.             criterr = TestCriticalError();
  555.         }
  556.         if (criterr)
  557.             return FALSE;
  558.         while (ax == 0)    {
  559.             if (!((attrib & 0x4000) &&
  560.                     (ff.ff_attrib & (attrib & 0x3f)) == 0) &&
  561.                         strcmp(ff.ff_name, "."))    {
  562.                 char fname[15];
  563.                 sprintf(fname, (ff.ff_attrib & 0x10) ?
  564.                                 "[%s]" : "%s" , ff.ff_name);
  565.                 dirlist = realloc(dirlist, sizeof(char *)*(i+1));
  566.                 if (dirlist != NULL)    {
  567.                     dirlist[i] = malloc(strlen(fname)+1);
  568.                     if (dirlist[i] != NULL)
  569.                         strcpy(dirlist[i], fname);
  570.                     i++;
  571.                 }
  572.             }
  573.             ax = findnext(&ff);
  574.         }
  575.         if (dirlist != NULL)    {
  576.             int j;
  577.             /* -- sort file/drive/directory list box data -- */
  578.             qsort(dirlist, i, sizeof(void *), dircmp);
  579.  
  580.             /* ---- send sorted list to list box ---- */
  581.             for (j = 0; j < i; j++)    {
  582.                 SendMessage(lwnd, ADDTEXT, (PARAM) dirlist[j], 0);
  583.                 free(dirlist[j]);
  584.             }
  585.             free(dirlist);
  586.         }
  587.         SendMessage(lwnd, SHOW_WINDOW, 0, 0);
  588.     }
  589.  
  590.     if (pathid)    {
  591.         fnmerge(path, drive, dir, NULL, NULL);
  592.         PutItemText(wnd, pathid, path);
  593.     }
  594.  
  595.     return TRUE;
  596. }
  597.  
  598. static CTLWINDOW *AssociatedControl(DBOX *db, enum commands Tcmd)
  599. {
  600.     CTLWINDOW *ct = db->ctl;
  601.     while (ct->class)    {
  602.         if (ct->class != TEXT)
  603.             if (ct->command == Tcmd)
  604.                 break;
  605.         ct++;
  606.     }
  607.     return ct;
  608. }
  609.  
  610. static void dbShortcutKeys(DBOX *db, int ky)
  611. {
  612.     CTLWINDOW *ct;
  613.     int ch = AltConvert(ky);
  614.  
  615.     if (ch != 0)    {
  616.         ct = db->ctl;
  617.         while (ct->class)    {
  618.             char *cp = ct->itext;
  619.             while (cp && *cp)    {
  620.                 if (*cp == SHORTCUTCHAR && tolower(*(cp+1)) == ch)    {
  621.                     if (ct->class == TEXT)
  622.                         ct = AssociatedControl(db, ct->command);
  623.                     if (ct->class == RADIOBUTTON)
  624.                         SetRadioButton(db, ct);
  625.                     else if (ct->class == CHECKBOX)    {
  626.                         ct->setting ^= ON;
  627.                         SendMessage(ct->wnd, PAINT, 0, 0);
  628.                     }
  629.                     else if (ct->class)    {
  630.                         SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  631.                         if (ct->class == BUTTON)
  632.                             SendMessage(ct->wnd, KEYBOARD, '\r', 0);
  633.                     }
  634.                     return;
  635.                 }
  636.                 cp++;
  637.             }
  638.             ct++;
  639.         }
  640.     }
  641. }
  642.  
  643. /* generic window processor used by all dialog box control windows */
  644. static int ControlProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  645. {
  646.     DBOX *db;
  647.     CTLWINDOW *ct;
  648.  
  649.     if (wnd == NULL)
  650.         return FALSE;
  651.     db = GetParent(wnd) ? GetParent(wnd)->extension : NULL;
  652.     ct = GetControl(wnd);
  653.  
  654.     switch (msg)    {
  655.         case CREATE_WINDOW:
  656.             ct = wnd->ct = wnd->extension;
  657.             wnd->extension = NULL;
  658.             if (ct != NULL)
  659.                 ct->wnd = wnd;
  660.             break;
  661.         case KEYBOARD:
  662.             switch ((int) p1)    {
  663.                 case F1:
  664.                     if (WindowMoving || WindowSizing)
  665.                         break;
  666.                     if (!DisplayHelp(wnd, ct->help))
  667.                         SendMessage(GetParent(wnd), COMMAND, ID_HELP, 0);
  668.                     return TRUE;
  669.                 case ' ':
  670.                     if (!((int)p2 & ALTKEY))
  671.                         break;
  672.                 case ALT_F6:
  673.                 case CTRL_F4:
  674.                 case ALT_F4:
  675.                     PostMessage(GetParent(wnd), msg, p1, p2);
  676.                     return TRUE;
  677.                 default:
  678.                     break;
  679.             }
  680.             if (GetClass(wnd) == EDITBOX)
  681.                 if (isMultiLine(wnd))
  682.                     break;
  683.             switch ((int) p1)    {
  684.                 case UP:
  685.                     if (!isDerivedFrom(wnd, LISTBOX))    {
  686.                         p1 = CTRL_FIVE;
  687.                         p2 = LEFTSHIFT;
  688.                     }
  689.                     break;
  690.                 case BS:
  691.                     if (!isDerivedFrom(wnd, EDITBOX))    {
  692.                         p1 = CTRL_FIVE;
  693.                         p2 = LEFTSHIFT;
  694.                     }
  695.                     break;
  696.                 case DN:
  697.                     if (!isDerivedFrom(wnd, LISTBOX) &&
  698.                             !isDerivedFrom(wnd, COMBOBOX))
  699.                         p1 = '\t';
  700.                     break;
  701.                 case FWD:
  702.                     if (!isDerivedFrom(wnd, EDITBOX))
  703.                         p1 = '\t';
  704.                     break;
  705.                 case '\r':
  706.                     if (isDerivedFrom(wnd, EDITBOX))
  707.                         if (isMultiLine(wnd))
  708.                             break;
  709.                     if (isDerivedFrom(wnd, BUTTON))
  710.                         break;
  711.                     SendMessage(GetParent(wnd), COMMAND, ID_OK, 0);
  712.                     return TRUE;
  713.                 default:
  714.                     break;
  715.             }
  716.             break;
  717.         case PAINT:
  718.             if (GetClass(wnd) == EDITBOX ||
  719.                     GetClass(wnd) == LISTBOX ||
  720.                         GetClass(wnd) == TEXTBOX)    {
  721.                 int oldattr = GetAttribute(wnd);
  722.                 if (wnd->wlines > ClientHeight(wnd))
  723.                     AddAttribute(wnd, VSCROLLBAR);
  724.                 else 
  725.                     ClearAttribute(wnd, VSCROLLBAR);
  726.                 if (wnd->textwidth > ClientWidth(wnd))
  727.                     AddAttribute(wnd, HSCROLLBAR);
  728.                 else 
  729.                     ClearAttribute(wnd, HSCROLLBAR);
  730.                 if (GetAttribute(wnd) != oldattr)
  731.                     SendMessage(wnd, BORDER, 0, 0);
  732.             }
  733.             break;
  734.         case BORDER:
  735.             if (GetClass(wnd) == EDITBOX)    {
  736.                 WINDOW oldFocus = inFocus;
  737.                 inFocus = NULL;
  738.                 DefaultWndProc(wnd, msg, p1, p2);
  739.                 inFocus = oldFocus;
  740.                 return TRUE;
  741.             }
  742.             break;
  743.         case SETFOCUS:
  744.             if (p1)    {
  745.                 DefaultWndProc(wnd, msg, p1, p2);
  746.                 GetParent(wnd)->dFocus = ct;
  747.                 SendMessage(GetParent(wnd), COMMAND,
  748.                     inFocusCommand(db), ENTERFOCUS);
  749.                 return TRUE;
  750.             }
  751.             else 
  752.                 SendMessage(GetParent(wnd), COMMAND,
  753.                     inFocusCommand(db), LEAVEFOCUS);
  754.             break;
  755.         case CLOSE_WINDOW:
  756.             if (ct != NULL)
  757.                 if (GetParent(wnd)->ReturnCode == ID_OK &&
  758.                         (ct->class == EDITBOX || ct->class == COMBOBOX))
  759.                     if (wnd->TextChanged)
  760.                         if ((ct->itext = realloc(ct->itext,    strlen(wnd->text)+1)) != NULL)    {
  761.                             strcpy(ct->itext, wnd->text);
  762.                             if (!isMultiLine(wnd))    {
  763.                                 char *cp = ct->itext+strlen(ct->itext)-1;
  764.                                 if (*cp == '\n')
  765.                                     *cp = '\0';
  766.                             }
  767.                         }
  768.             break;
  769.         default:
  770.             break;
  771.     }
  772.     return DefaultWndProc(wnd, msg, p1, p2);
  773. }
  774.  
  775. /* ----- Create unambiguous path from file spec, filling in the
  776.      drive and directory if incomplete. Optionally change to
  777.      the new drive and subdirectory ------ */
  778. void CreatePath(char *path, char *fspec, int InclName, int Change)
  779. {
  780.     int cm = 0;
  781.     unsigned currdrive;
  782.     char currdir[64];
  783.     char *cp;
  784.  
  785.     if (!Change)    {
  786.         /* ----- save the current drive and subdirectory ----- */
  787.         currdrive = getdisk();
  788.         getcwd(currdir, sizeof currdir);
  789.         memmove(currdir, currdir+2, strlen(currdir+1));
  790.         cp = currdir+strlen(currdir)-1;
  791.         if (*cp == '\\')
  792.             *cp = '\0';
  793.     }
  794.  
  795.     *drive = *dir = *name = *ext = '\0';
  796.     fnsplit(fspec, drive, dir, name, ext);
  797.     if (!InclName)
  798.         *name = *ext = '\0';
  799.     *drive = toupper(*drive);
  800.  
  801.     if (*ext)
  802.         cm |= EXTENSION;
  803.     if (InclName && *name)
  804.         cm |= FILENAME;
  805.     if (*dir)
  806.         cm |= DIRECTORY;
  807.     if (*drive)
  808.         cm |= DRIVE;
  809.  
  810.     if (cm & DRIVE)
  811.         setdisk(*drive - 'A');
  812.     else     {
  813.         *drive = getdisk();
  814.         *drive += 'A';
  815.     }
  816.  
  817.     if (cm & DIRECTORY)    {
  818.         cp = dir+strlen(dir)-1;
  819.         if (*cp == '\\')
  820.             *cp = '\0';
  821.         chdir(dir);
  822.     }
  823.     getcwd(dir, sizeof dir);
  824.     memmove(dir, dir+2, strlen(dir+1));
  825.  
  826.     if (InclName)    {
  827.         if (!(cm & FILENAME))
  828.             strcpy(name, "*");
  829.         if (!(cm & EXTENSION) && strchr(fspec, '.') != NULL)
  830.             strcpy(ext, ".*");
  831.     }
  832.     else
  833.         *name = *ext = '\0';
  834.     if (dir[strlen(dir)-1] != '\\')
  835.         strcat(dir, "\\");
  836.     memset(path, 0, sizeof path);
  837.     fnmerge(path, drive, dir, name, ext);
  838.  
  839.     if (!Change)    {
  840.         setdisk(currdrive);
  841.         chdir(currdir);
  842.     }
  843. }
  844.  
  845. static void ChangeFocus(WINDOW wnd, int direc)
  846. {
  847.     DBOX *db = wnd->extension;
  848.      CTLWINDOW *ct = db->ctl;
  849.      CTLWINDOW *ctt;
  850.  
  851.     /* --- find the control that has the focus --- */
  852.     while (ct->class)    {
  853.         if (ct == wnd->dFocus)
  854.             break;
  855.         ct++;
  856.     }
  857.     if (ct->class)    {
  858.         ctt = ct;
  859.         do    {
  860.             /* ----- point to next or previous control ----- */
  861.             if (direc)    {
  862.                 ct++;
  863.                 if (ct->class == 0)
  864.                     ct = db->ctl;
  865.             }
  866.             else    {
  867.                 if (ct == db->ctl)
  868.                     while (ct->class)
  869.                         ct++;
  870.                 --ct;
  871.             }
  872.  
  873.             if (ct->class != BOX && ct->class != TEXT)    {
  874.                 SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  875.                 SendMessage(ctt->wnd, PAINT, 0, 0);
  876.                 SendMessage(ct->wnd, PAINT, 0, 0);
  877.                 break;
  878.             }
  879.         } while (ct != ctt);
  880.     }
  881. }
  882.